/*
Macros:
CONSTANT_COLOR = 0, 1
VERTEX_COLOR = 0, 1
TEXTURE = 0, 1
NORMAL_TEXTURE = 0, 1
ALPHA_TEST = 0, 1
TEX_COORD_TRANSFORM = 0, 1
SKINNING = 0, 1
*/

float4x4 g_World;
float4x4 g_WorldViewProj;

#if CONSTANT_COLOR == 1
	float4 g_ConstantColor;
#endif

#if TEXTURE == 1
	texture g_DiffuseTexture;
	sampler DiffuseSampler = sampler_state {
		Texture = (g_DiffuseTexture);
		AddressU = WRAP;
		AddressV = WRAP;
		MinFilter = LINEAR;
		MagFilter = LINEAR;
		MipFilter = LINEAR;
	};
#endif

#if NORMAL_TEXTURE != 0
	texture g_NormalTexture;
	sampler NormalSampler = sampler_state {
		Texture = (g_NormalTexture);
		AddressU = WRAP;
		AddressV = WRAP;
		MinFilter = LINEAR;
		MagFilter = LINEAR;
		MipFilter = LINEAR;
	};
#endif

#if ALPHA_TEST != 0
	float g_AlphaTestRef;
#endif

#if TEX_COORD_TRANSFORM != 0
	float4x2 g_TexCoordTransform;
#endif

#if SKINNING != 0
	float4x3 g_BoneMatrices[32];
#endif

#if TEXTURE == 1 || NORMAL_TEXTURE != 0
	#define USE_TEXCOORD
#endif

struct APP_TO_VS
{
	float3 Pos : POSITION;
	float3 Normal : NORMAL;
	#if VERTEX_COLOR != 0
		float4 Color : COLOR0;
	#endif
	#if SKINNING != 0
		half BoneWeight0 : BLENDWEIGHT0;
		int4 BoneIndices : BLENDINDICES0;
	#endif
	#ifdef USE_TEXCOORD
		float2 TexCoord : TEXCOORD0;
	#endif
	#if NORMAL_TEXTURE != 0
		float3 Tangent : TANGENT;
		float3 Bitangent : BINORMAL;
	#endif
};

#if SKINNING != 0
	float3 SkinPos(float3 Pos, APP_TO_VS Input)
	{
		float3 OutputPos = mul(float4(Pos, 1), g_BoneMatrices[Input.BoneIndices[0]]) * Input.BoneWeight0;
		OutputPos += mul(float4(Pos, 1), g_BoneMatrices[Input.BoneIndices[1]]) * (1 - Input.BoneWeight0);
		return OutputPos;
	}
	
	float3 SkinNormal(float3 Normal, APP_TO_VS Input)
	{
		float3 OutputNormal = mul(Normal, (float3x3)g_BoneMatrices[Input.BoneIndices[0]]) * Input.BoneWeight0;
		OutputNormal += mul(Normal, (float3x3)g_BoneMatrices[Input.BoneIndices[1]]) * (1 - Input.BoneWeight0);
		return OutputNormal;
	}

	float3 SkinTangent(float3 Tangent, APP_TO_VS Input)
	{
		return SkinNormal(Tangent, Input);
	}
#endif

float3 PreprocessLocalPos(APP_TO_VS In)
{
	float3 inPos = In.Pos;
	#if SKINNING != 0
		return SkinPos(In.Pos, In);
	#else
		return In.Pos;
	#endif
}

float4 CalcGeometryPos(APP_TO_VS In)
{
	float3 pos_Local = PreprocessLocalPos(In);
	return mul(float4(pos_Local, 1), g_WorldViewProj);
}

float3 PreprocessLocalNormal(APP_TO_VS In)
{
	#if SKINNING != 0
		return SkinNormal(In.Normal, In);
	#else
		return In.Normal;
	#endif
}

#if NORMAL_TEXTURE != 0
	float3 PreprocessLocalTangent(APP_TO_VS In)
	{
		#if SKINNING != 0
			return SkinTangent(In.Tangent, In);
		#else
			return In.Tangent;
		#endif
	}
	float3 PreprocessLocalBitangent(APP_TO_VS In)
	{
		#if SKINNING != 0
			return SkinTangent(In.Bitangent, In);
		#else
			return In.Bitangent;
		#endif
	}
#endif

#ifdef USE_TEXCOORD
	float2 CalcTexCoord(APP_TO_VS In)
	{
		#if TEX_COORD_TRANSFORM != 0
			return mul(In.TexCoord, (float2x2)g_TexCoordTransform) + g_TexCoordTransform._41_42;
		#else
			return In.TexCoord;
		#endif
	}
#endif

